#include<sys/socket.h>
#include<stdio.h>
#include<errno.h>
#include<netinet/in.h>
#include<string.h>
#include<pthread.h>
#include <sys/select.h>
#include<poll.h>
#include<sys/epoll.h>
void *client_thread(void *arg)
{
    int clientfd = * (int *)arg;

    while(1)
    {char buf[128] = {0};
    int count = recv(clientfd,buf,128,0);
    if(count == -1)
    { perror("count");close(clientfd);return NULL;}
    if(count == 0)
    {close(clientfd);return NULL;}
    send(clientfd,buf,count,0);
    printf("clientfd : %d,count:  %d,buf: %s\n",clientfd,count,buf);}
    
     close(clientfd);
}


int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);

    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(struct sockaddr_in));

    serveraddr.sin_family  =  AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(2047);

    if(-1 == (bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr))))
    {
        perror("bind");
        return -1;
    }

    listen(sockfd,10);
#if 0
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    int clientfd = accept(sockfd,(struct sockaddr*)&clientaddr,&len);
    printf("accept\n");
#if 0
char buf[128] = {0};
    int count = recv(clientfd,buf,128,0);
    if(count == -1)
    { perror("count");return -1;}
    send(clientfd,buf,128,0);
    printf("socked : %d,clientfd : %d,count:  %d\n",sockfd,clientfd,count);
    }
#else
    while(1)
    {   
         char buf[128] = {0};
    int count = recv(clientfd,buf,128,0);
    if(count == -1)
    { perror("count");close(clientfd);return NULL;}
    if(count == 0)
    {break;}
    send(clientfd,buf,count,0);
    printf("socked : %d,clientfd : %d,count:  %d,buf: %s\n",sockfd,clientfd,count,buf);
    }

#endif

#elif 0
while(1){
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    int clientfd = accept(sockfd,(struct sockaddr*)&clientaddr,&len);
    
    pthread_t thid;
    pthread_create(&thid,NULL,client_thread,&clientfd);

}
#elif 0
//select

    fd_set rfds,rset;
    FD_ZERO(&rfds);
    FD_SET(sockfd,&rfds);

    int maxfd = sockfd;
    while(1)
    {
        rset = rfds;
        int nready = select(maxfd+1,&rset,NULL,NULL,NULL);
        if(FD_ISSET(sockfd,&rset))
        {
            struct sockaddr_in clientaddr;
            socklen_t len = sizeof(clientaddr);
            int clientfd = accept(sockfd,(struct sockaddr*)&clientaddr,&len);

            printf("socked : %d,clientfd : %d\n",sockfd,clientfd);
            FD_SET(clientfd,&rfds);       
            maxfd = clientfd;
            printf("clientfd\n");
        }

            int i = 0;
            for( i = sockfd + 1;i <= maxfd;i++)
            {
                if(FD_ISSET(i,&rset))
                {
                    char buf[128] = {0};
                    int count = recv(i,buf,128,0);
                    if(count == -1)
                    { perror("count");close(i);}
                    if(count == 0)
                    {close(i);}
                    printf("receive\n");
                    send(i,buf,count,0);
                    printf("clientfd : %d,count:  %d,buf: %s\n",i,count,buf);
                }
                            
            }
        
    }

/* #if 0//select

    fd_set rfds, rset;
    FD_ZERO(&rfds);
    FD_SET(sockfd, &rfds);  // 初始只监控监听套接字

    int maxfd = sockfd;     // 记录最大文件描述符
    while(1)
    {
        rset = rfds;  // 每次select前复制读集合（因为select会修改集合）
        // select第一个参数是最大fd+1，超时设为NULL表示阻塞等待
        int nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
        if (nready < 0) {
            perror("select error");
            break;
        }

        // 步骤1：处理新客户端连接（监听套接字就绪）
        if (FD_ISSET(sockfd, &rset)) {
            struct sockaddr_in clientaddr;
            socklen_t len = sizeof(clientaddr);
            int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);
            if (clientfd < 0) {
                perror("accept error");
                continue;
            }
            // 将新客户端fd加入监控集合
            FD_SET(clientfd, &rfds);
            // 更新最大fd（select需要）
            if (clientfd > maxfd) {
                maxfd = clientfd;
            }
            printf("新客户端连接: sockfd=%d, clientfd=%d\n", sockfd, clientfd);
            
            // 减少就绪计数（如果没有其他就绪事件，可跳过后续检查）
            if (--nready <= 0) {
                continue;
            }
        }

        // 步骤2：处理已有客户端的数据（遍历所有客户端fd，检查是否就绪）
        // 注意：必须遍历所有可能的fd，不能只在新连接时处理
        int i = 0;
        for ( i = sockfd + 1; i <= maxfd; i++) {
            // 检查当前fd是否在就绪集合中
            if (FD_ISSET(i, &rset)) {
                char buf[128] = {0};
                int count = recv(i, buf, sizeof(buf)-1, 0);  // 使用i（当前客户端fd）
                
                if (count == -1) {  // 接收错误
                    perror("recv error");
                    close(i);
                    FD_CLR(i, &rfds);  // 从监控集合中移除
                } else if (count == 0) {  // 客户端断开连接
                    printf("客户端断开: clientfd=%d\n", i);
                    close(i);
                    FD_CLR(i, &rfds);  // 从监控集合中移除
                } else {  // 正常接收数据，回发给客户端
                    send(i, buf, count, 0);  // 用i发送给当前客户端
                    printf("clientfd=%d, 接收数据: %s (长度: %d)\n", i, buf, count);
                }
                // 处理完一个就绪fd，减少计数
                if (--nready <= 0) {
                    break;  // 没有更多就绪事件，跳出循环
                }
            }
        }
    }
 */



#elif 0//poll

    struct pollfd fds[1024] = {0};
    fds[sockfd].fd = sockfd;
    fds[sockfd].events = POLLIN;
    int maxfd = sockfd;
    while(1){
        poll(fds,maxfd+1,-1);
        if(fds[sockfd].revents & POLLIN){
            struct sockaddr_in clientaddr;
            socklen_t len = sizeof(clientaddr);
            int clientfd = accept(sockfd,(struct sockaddr*)&clientaddr,&len);
            printf("socked : %d,clientfd : %d\n",sockfd,clientfd);
            
                fds[clientfd].fd = clientfd;
                fds[clientfd].events = POLLIN;

                maxfd = clientfd;
        }
        int i = 0;
        for(i = sockfd+1;i<=maxfd;i++)
        {
        if(fds[i].revents & POLLIN){
                char buf[128] = {0};
                int count = recv(i,buf,128,0);
                if(count == 0)
                {
                     fds[i].fd = -1;
                     fds[i].events = 0;
                     close(i);

                }
                printf("receive\n");
                send(i,buf,count,0);
                printf("clientfd : %d,count:  %d,buf: %s\n",i,count,buf);
        }

    }
}

#else//epoll

    int epfd = epoll_create(1);
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = sockfd;

    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ev);
    struct epoll_event events[1024] = {0};
    while(1){
        int nready = epoll_wait(epfd,events,1024,-1);
        int i= 0;
        for(i= 0;i<nready;i++)
        {
            int connfd = events[i].data.fd;
            if(sockfd == connfd)
            {
                struct sockaddr_in clientaddr;
                socklen_t len = sizeof(clientaddr);
                int clientfd = accept(sockfd,(struct sockaddr*)&clientaddr,&len);
                printf("socked : %d,clientfd : %d\n",sockfd,clientfd);

                ev.events = EPOLLIN;
                ev.data.fd = clientfd;
               epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ev);

               printf("clientfd: %d\n",clientfd);

            }
            else if(events[i].events & EPOLLIN)
            {
                 char buf[128] = {0};
                int count = recv(connfd,buf,128,0);
                if(count == 0)
                {
                    epoll_ctl(epfd,EPOLL_CTL_DEL,connfd,NULL);
                     close(i);

                }
                printf("receive\n");
                send(i,buf,count,0);
                printf("clientfd : %d,count:  %d,buf: %s\n",i,count,buf);
            }
        }

    }




#endif
    getchar(); 
   
}